package com.ydd.mqserver.config;


import com.ydd.mqserver.base.ExchangeName;
import com.ydd.mqserver.base.QueueNames;
import com.ydd.mqserver.base.RoutingKeyName;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/***
 *RabbitMQ消息丢失解决方案
 * 方案1 ：开启RabbitMQ事务 缺点： RabbitMQ 事务机制是同步的，你提交一个事务之后会阻塞在那儿，采用这种方式基本上吞吐量会下来，因为太耗性能。
 *
 *方案2： 使用confirm机制  confirm 机制是异步的 在生产者开启了confirm模式之后，每次写的消息都会分配一个唯一的id，然后如果写入了rabbitmq之中，
 * rabbitmq会给你回传一个ack消息，告诉你这个消息发送OK了；如果rabbitmq没能处理这个消息，会回调你一个nack接口，告诉你这个消息失败了，你可以进行重试。
 * 而且你可以结合这个机制知道自己在内存里维护每个消息的id，如果超过一定时间还没接收到这个消息的回调，那么你可以进行重发。
 *
 *
 * 开启rabbitMQ的持久化机制
 * 关闭消费者自动ack
 */
@Slf4j
@Configuration
public class QueueConfig {


    /***
     * 交换机
     * @return
     */
    @Bean
    public DirectExchange notifyMsgDirectExchange() {
        return new DirectExchange(ExchangeName.NOTIFY_MSG);
    }

    /***
     * 队列
     * @return
     *
     * durable:是否持久化,默认是false,持久化队列：会被存储在磁盘上，当消息代理重启时仍然存在，暂存队列：当前连接有效
     * exclusive:该队列是否只供一个消费者进行消费是否进行消息共享，true可以多个消费者消费，false:只能-一个消费者消费
     * autoDelete:是否自动删除，当没有生产者或者消费者使用此队列，该队列会自动删除。
     */
    @Bean
    public Queue notifyMsgQueue() {
        return new Queue(QueueNames.NOTIFY_MSG_QUEUE);
    }


    /**
     * 绑定
     */
    @Bean
    public Binding notifyMsgQueueBinding() {
        // 将消息队列绑定到直连交换机，并指定路由键为notify_msg_key
        return BindingBuilder
                .bind(notifyMsgQueue())
                .to(notifyMsgDirectExchange())
                .with(RoutingKeyName.NOTIFY_MSG_KEY);
    }





}
